package com.why.mojo;

import com.why.dto.Api;
import com.why.generate.GenerateWordDoc;
import com.why.reflect.AnnotationParse;
import com.why.util.StringUtil;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoFailureException;
import org.codehaus.plexus.util.StringUtils;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/*
 * @goal CustomMavenMojo：表示该插件的服务目标
 * @phase compile：表示该插件的生效周期阶段
 * @requiresProject false：表示是否依托于一个项目才能运行该插件
 * @parameter expression="${name}"：表示插件参数，使用插件的时候会用得到
 * @required:代表该参数不能省略
 */

/**
 * @goal word
 */
public class WordDocGeneratorMojo extends AbstractMojo {
    /**
     * jar of the classes.
     *
     * @parameter property="jarPath"
     */
    private String jarPath;
    /**
     * package of the classes.
     *
     * @parameter property="apiPackage"
     */
    private String apiPackage;
    /**
     * path of the classes folder.
     *
     * @parameter property="classFolderPath"
     */
    private String classFolderPath;

    /**
     * all class name of the api.
     *
     * @parameter property="apiClassName"
     */
    private String apiClassName;

    /**
     * method name of the api.
     *
     * @parameter property="apiMethodName"
     */
    private String apiMethodName;

    /**
     * param all class name of the api.
     *
     * @parameter property="apiParamClassName"
     */
    private String apiParamClassName;

    /**
     * path of the maven repository.
     *
     * @parameter property="repositoryPath"
     * @required
     */
    private String repositoryPath;
    /**
     * path of the template file.
     *
     * @parameter property="mainFilePath"
     * @required
     */
    private String mainFilePath;
    /**
     * path of the template file.
     *
     * @parameter property="templateFilePath"
     * @required
     */
    private String templateFilePath;

    /**
     * path of the template file.
     *
     * @parameter property="requestTempleFilePath"
     */
    private String requestTempleFilePath;

    /**
     * path of the output file.
     *
     * @parameter property="outputFilePath"
     * @required
     */
    private String outputFilePath;

    // 放射解析出反射类
    private AnnotationParse annotationParse;

    @Override
    public void execute() throws MojoFailureException {
        checkParam();
        loadJar();
        // 执行
        try {
            run();
        } catch (Exception e) {
            getLog().error(e);
            throw new MojoFailureException("执行失败" + e.getClass().getName() + "：" + e.getMessage());
        }

        getLog().info("处理完毕！！！");
    }

    /**
     * 业务入口
     *
     * @throws Exception
     */
    private void run() throws Exception {
        // 获得Api对象
        getLog().info("开始获取Api对象");
        List<Api> apis = annotationParse.generateApisObj(jarPath, apiPackage, apiClassName, apiMethodName, apiParamClassName);
        apis.forEach(api -> {
            api.setRequestTempleFilePath(requestTempleFilePath);
        });
        getLog().info("得到Api对象：" + apis.toString());

        // 生成doc文档
        getLog().info("开始生成word文档");
        GenerateWordDoc generateWordDoc = new GenerateWordDoc();
//        generateWordDoc.generateWordDoc(api, templateFilePath, outputFilePath);
        generateWordDoc.generateWordDocs(apis, mainFilePath, templateFilePath, outputFilePath);
        getLog().info("得到word文档：" + outputFilePath);
    }


    private void loadJar() throws MojoFailureException {
        // 使用自定义类加载器加载指定目录下的jar包或class文件
        // 需要加载当前项目编译后class文件所在根路径和maven本地仓库根目录
        try {
            getLog().info("加载项目class文件和本地仓库jar包");

            // 获取maven本地仓库的所有jar包全路径
            List<String> jarPaths = getRepositoryJarPaths();
            if (!StringUtil.isEmpty(jarPath)) {
                jarPaths.add(jarPath);
            }
            int size = jarPaths.size() + 1;
            URL[] urls = new URL[size];
            int i = 0;
            // jar包URL
            for (; i < size - 1; i++) {
                urls[i] = new URL("file:/" + jarPaths.get(i));
            }
            // 项目class文件URL
            urls[size - 1] = new URL("file:/" + classFolderPath);

            annotationParse = new AnnotationParse(urls);
            getLog().info("加载成功");
        } catch (Exception e) {
            getLog().error(e);
            throw new MojoFailureException("初始化类加载器失败!" + e.getClass().getName() + "：" + e.getMessage());
        }
    }

    /**
     * 获取所有jar包全路径集合
     *
     * @return List
     */
    private List<String> getRepositoryJarPaths() {
        List<String> filePaths = new ArrayList<>();
        File file = new File(repositoryPath);
        return ergodic(file, filePaths);
    }

    /**
     * 递归遍历目录，将jar包路径放进list
     *
     * @param file
     * @param resultFileName
     * @return
     */
    private static List<String> ergodic(File file, List<String> resultFileName) {
        File[] files = file.listFiles();
        // 判断目录下是不是空的
        if (files == null) {
            return resultFileName;
        }
        for (File f : files) {
            // 判断是否文件夹
            if (f.isDirectory()) {
                // 调用自身,查找子目录
                ergodic(f, resultFileName);
            } else {
                if (f.getName().endsWith(".jar")) {
                    resultFileName.add(f.getPath());
                }
            }
        }
        return resultFileName;
    }

    private void checkParam() throws MojoFailureException {
        if (StringUtils.isEmpty(repositoryPath)) {
            throw new MojoFailureException("repositoryPath！");
        }
        if (StringUtils.isEmpty(templateFilePath)) {
            throw new MojoFailureException("templateFilePath！");
        }
        if (StringUtils.isEmpty(outputFilePath)) {
            throw new MojoFailureException("outputFilePath！");
        }
    }

    public String getJarPath() {
        return jarPath;
    }

    public void setJarPath(String jarPath) {
        this.jarPath = jarPath;
    }

    public String getApiPackage() {
        return apiPackage;
    }

    public void setApiPackage(String apiPackage) {
        this.apiPackage = apiPackage;
    }

    public String getClassFolderPath() {
        return classFolderPath;
    }

    public void setClassFolderPath(String classFolderPath) {
        this.classFolderPath = classFolderPath;
    }

    public String getApiClassName() {
        return apiClassName;
    }

    public void setApiClassName(String apiClassName) {
        this.apiClassName = apiClassName;
    }

    public String getApiMethodName() {
        return apiMethodName;
    }

    public void setApiMethodName(String apiMethodName) {
        this.apiMethodName = apiMethodName;
    }

    public String getApiParamClassName() {
        return apiParamClassName;
    }

    public void setApiParamClassName(String apiParamClassName) {
        this.apiParamClassName = apiParamClassName;
    }

    public String getRepositoryPath() {
        return repositoryPath;
    }

    public void setRepositoryPath(String repositoryPath) {
        this.repositoryPath = repositoryPath;
    }

    public String getTemplateFilePath() {
        return templateFilePath;
    }

    public void setTemplateFilePath(String templateFilePath) {
        this.templateFilePath = templateFilePath;
    }

    public String getOutputFilePath() {
        return outputFilePath;
    }

    public void setOutputFilePath(String outputFilePath) {
        this.outputFilePath = outputFilePath;
    }

    public String getRequestTempleFilePath() {
        return requestTempleFilePath;
    }

    public void setRequestTempleFilePath(String requestTempleFilePath) {
        this.requestTempleFilePath = requestTempleFilePath;
    }

    public String getMainFilePath() {
        return mainFilePath;
    }

    public void setMainFilePath(String mainFilePath) {
        this.mainFilePath = mainFilePath;
    }
}
